package middleware

import (
	"gin_blog/utils"
	"gin_blog/utils/errmsg"
	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v5"
	"net/http"
	"strings"
	"time"
)

var JwtKey = []byte(utils.JwtKey)
var code int

type MyClaims struct {
	Username             string `json:"username"`
	jwt.RegisteredClaims        // jwt v3版本为 jwt.StandardClaims
	//jwt.Claims
}

// SetToken 生成token
func SetToken(username string) (string, int) {
	expireTime := time.Now().Add(10 * time.Hour)
	setClaims := MyClaims{
		Username: username,
		RegisteredClaims: jwt.RegisteredClaims{
			// ExpiresAt: expireTime.Unix(),  // 会报错显示Unix不可用,使用jwt.NumericDate()函数进行转换
			ExpiresAt: jwt.NewNumericDate(expireTime), // 过期时间10小时
			Issuer:    "gin_blog",
		},
	}

	reqClaim := jwt.NewWithClaims(jwt.SigningMethodHS256, setClaims)
	token, err := reqClaim.SignedString(JwtKey)

	if err != nil {
		return "", errmsg.ERROR
	}
	return token, errmsg.SUCCESS
}

func Secret() jwt.Keyfunc {
	return func(token *jwt.Token) (interface{}, error) {
		return JwtKey, nil
	}
}

// CheckToken 验证token
func CheckToken(token string) (*MyClaims, int) {
	setToken, _ := jwt.ParseWithClaims(token, &MyClaims{}, Secret())
	if key, _ := setToken.Claims.(*MyClaims); setToken.Valid {
		return key, errmsg.SUCCESS
	} else {
		return nil, errmsg.ERROR
	}
}

// jwt中间件
func JwtToken() gin.HandlerFunc {
	return func(c *gin.Context) {
		tokenHeader := c.Request.Header.Get("Authorization")
		if tokenHeader == "" {
			code = errmsg.ERROR_TOKEN_NOT_EXIST
			c.JSON(http.StatusOK, gin.H{
				"code": code,
				"msg":  errmsg.GetErrMsg(code),
			})
			c.Abort()
			return
		}

		checkToken := strings.SplitN(tokenHeader, " ", 2)
		if len(checkToken) != 2 && checkToken[0] != "Bearer" {
			code = errmsg.ERROR_TOKEN_WRONG
			c.JSON(http.StatusOK, gin.H{
				"code": code,
				"msg":  errmsg.GetErrMsg(code),
			})
			c.Abort()
			return
		}

		key, Tcode := CheckToken(checkToken[1])
		if Tcode == errmsg.ERROR {
			code = errmsg.ERROR_TOKEN_WRONG
			c.JSON(http.StatusOK, gin.H{
				"code": code,
				"msg":  errmsg.GetErrMsg(code),
			})
			c.Abort()
			return
		}

		// 处理token超时
		//if time.Now().Unix() > key.ExpiresAt {
		//	code = errmsg.ERROR_TOKEN_RUNTIME
		//  c.Abort()
		//}

		c.Set("username", key.Username)
		c.Next()
	}
}
